/*!
 * \file nuMacApplication.cpp
 * \brief Application class for Mac.
 * \author Nus
 * \date 2008/03/09, 21:15
 */

#include "nuMacApplication.h"

BEGIN_RTTI_IMPL(nuMacApplication);
  RTTI_IMPL(nuMacApplication, nuApplication);
END_RTTI_IMPL(nuMacApplication);

// Window reference.
WindowRef nuMacApplication::mWindowRef;

//! \brief Window event hadler.
static OSStatus WindowEventHandler(EventHandlerCallRef nexthandler,
                                   EventRef theevent,
                                   void *userdata);

// Window event hadler.
static OSStatus WindowEventHandler(EventHandlerCallRef nexthandler,
                                   EventRef theevent,
                                   void *userdata)
{
  OSStatus error = eventNotHandledErr;
  UInt32 EvClass = GetEventClass(theevent);
  UInt32 EvKind = GetEventKind(theevent);

  switch(EvClass) {
  case kEventClassWindow:
    switch(EvKind) {
    case kEventWindowBoundsChanged:
      {
        // Resize...
        Rect rectport;
        GetWindowPortBounds(nuMacApplication::getWindowRef(), &rectport);
      }
      error = noErr;
      break;
    case kEventWindowClosed:
      QuitApplicationEventLoop();
      break;
    default:
      break;
    }
    break;
  case kEventClassKeyboard:
    switch(EvKind) {
    case kEventRawKeyDown:
      {
        int key_down;
        GetEventParameter(theevent, kEventParamKeyCode, typeUInt32,
                          NULL, sizeof(int), NULL, &key_down);
      }
      break;
    case kEventRawKeyUp:
      {
        int key_up;
        GetEventParameter(theevent, kEventParamKeyCode, typeUInt32,
                          NULL, sizeof(int), NULL, &key_up);
      }
      break;
    default:
      break;
    }
    break;
  case kEventClassMouse:
    switch(EvKind) {
    case kEventMouseDragged:
      break;
    default:
      break;
    }
  }
  return error;
}

// Default constructor.
nuMacApplication::nuMacApplication()
    : mOsStatus(0)
{
  // Register all events.
  // Keyboards...
  mMacEvent << nuMacEvent::Evt(kEventClassKeyboard, kEventRawKeyDown);
  mMacEvent << nuMacEvent::Evt(kEventClassKeyboard, kEventRawKeyRepeat);
  mMacEvent << nuMacEvent::Evt(kEventClassKeyboard, kEventRawKeyUp);
  // Mouse...
  mMacEvent << nuMacEvent::Evt(kEventClassMouse, kEventMouseDragged);
  // Window...
  mMacEvent << nuMacEvent::Evt(kEventClassWindow, kEventWindowBoundsChanged);
  mMacEvent << nuMacEvent::Evt(kEventClassWindow, kEventWindowClosed);
}

// Default destructor.
nuMacApplication::~nuMacApplication()
{
  // None...
}

// Initialize application.
s32 nuMacApplication::initApp(void)
{
  return nuApplication::initApp();
}

// Run application.
s32 nuMacApplication::runApp(void)
{
  return nuApplication::runApp();
}

// Terminate application.
s32 nuMacApplication::termApp(void)
{
  return nuApplication::termApp();
}

// Initializing procedure.
s32 nuMacApplication::initProc(void)
{
  IBNibRef nib_ref;
  
  // Create a Nib reference passing the name of the nib file (without
  // the .nib extension).
  // CreateNibReference only searches into the application bundle.
  mOsStatus = CreateNibReference(CFSTR("main"), &nib_ref);
  if(mOsStatus)
    return EC_CRITICAL_ERROR;
  
  // Once the nib reference is created, set the menu bar.
  // "MainMenu" is the name of the menu bar object.
  // This name is set in InterfaceBuilder when the nib is created.
  mOsStatus = SetMenuBarFromNib(nib_ref, CFSTR("MenuBar"));
  if(mOsStatus)
    return EC_CRITICAL_ERROR;

  // Then create a window. "MainWindow" is the name of the window object.
  // This name is set in InterfaceBuilder when the nib is created.
  mOsStatus = CreateWindowFromNib(nib_ref, CFSTR("MainWindow"),
                                  &nuMacApplication::mWindowRef);
  if(mOsStatus)
    return EC_CRITICAL_ERROR;

  // Installing event handler
  mWindowEventHandlerUPP = NewEventHandlerUPP(WindowEventHandler);
  InstallWindowEventHandler(nuMacApplication::mWindowRef,
                            mWindowEventHandlerUPP,
                            mMacEvent.getSize(),
                            mMacEvent.getEventList(),
                            NULL,
                            NULL);

  // We don't need the nib reference anymore.
  DisposeNibReference(nib_ref);

  return nuApplication::initProc();
}

// Main procedure.
s32 nuMacApplication::mainProc(void)
{
  // Position new windows in a staggered arrangement on the main screen
  RepositionWindow(nuMacApplication::mWindowRef,
                   NULL,
                   kWindowCascadeOnMainScreen);

  // The window was created hidden so show it.
  ShowWindow(nuMacApplication::mWindowRef);

  // Call the event loop
  RunApplicationEventLoop();

  return nuApplication::initProc();
}

// Terminating procedure.
s32 nuMacApplication::termProc(void)
{
  return nuApplication::termProc();
}

// Resize.
void nuMacApplication::procResize(const nuRect& rect)
{

}

// Process key input.
void nuMacApplication::procInput(s32 state, s32 key)
{

}

// Process pointing devices.
void nuMacApplication::procPointingDev(s32 state, const nuPoint& point)
{

}
